#include "remotetablemodel.h"
#include <QDebug>
#include <QDateTime>

RemoteTableModel::RemoteTableModel(const QString &tableName,
                                   std::shared_ptr<DBClientThreadHandler> client,
                                   QObject *parent)
    : QAbstractTableModel(parent),
      m_tableName(tableName),
      m_client(client),
      m_pageSize(20),
      m_currentPage(1),
      m_totalCount(0),
      m_totalPages(1)
{
    connect(this, &RemoteTableModel::loadFinished, this, &RemoteTableModel::handleDataLoaded);
}

int RemoteTableModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return m_records.size();
}

int RemoteTableModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return m_headers.size();
}

QVariant RemoteTableModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid() || index.row() >= m_records.size())
        return QVariant();

    if (role == Qt::DisplayRole || role == Qt::EditRole)
    {
        const auto &record = m_records[index.row()];
        QString englishKey = COLUMN_ORDER.at(index.column());

        if (!record.contains(englishKey))
        {
            qWarning() << "键不存在:" << englishKey
                       << "可用键:" << record.keys();
            return QVariant();
        }

        QVariant value = record.value(englishKey);

        return value;
    }

    return QVariant();
}
QVariant RemoteTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role != Qt::DisplayRole)
        return QVariant();

    if (orientation == Qt::Horizontal)
    {
        if (section >= 0 && section < m_headers.size())
            return m_headers.at(section);
    }
    return section + 1;
}

void RemoteTableModel::setPageSize(int size)
{
    if (size != m_pageSize && size > 0)
    {
        m_pageSize = size;
        m_currentPage = 1;
    }
}

int RemoteTableModel::totalCount() const
{
    return m_totalCount;
}

void RemoteTableModel::refresh(const QString &filter)
{
    m_filter = filter;

    loadPage(m_currentPage);
}

void RemoteTableModel::initHeader(const QMap<QString, QString> &columnMapping, const QStringList &columnOrder)
{
    COLUMN_MAPPING = columnMapping;
    COLUMN_ORDER = columnOrder;

    for (const auto &key : COLUMN_ORDER)
    {
        m_headers.append(COLUMN_MAPPING.value(key));
    }
}

QString RemoteTableModel::getTableName() const
{
    return m_tableName;
}

bool RemoteTableModel::removeRow(int row, const QString &sql)
{
    if (m_loading)
        return false;
    m_loading = true;

    auto callback = [this, row](bool result)
    {
        if (result)
        {
            // 本地删除记录
            beginRemoveRows(QModelIndex(), row, row);
            m_records.removeAt(row);
            endRemoveRows();
        }
        m_loading = false;
        m_totalCount = m_totalCount - 1;
        return result;
    };

    m_client->ExecuteOther(
        sql.toStdString(),
        callback);

    return true;
}

bool RemoteTableModel::insertRow(const QVariantMap &data)
{
    if (m_loading)
        return false;
    m_loading = true;

    // 构建 INSERT 语句
    QStringList columns, values;
    for (auto it = data.begin(); it != data.end(); ++it)
    {
        columns << it.key();
        QString escaped;
        if (it.value().canConvert<QByteArray>())
        {
            escaped = QString::fromUtf8(it.value().toByteArray())
                          .replace("'", "''");
        }
        else
        {
            escaped = it.value().toString().replace("'", "''");
        }
        values << QString("'%1'").arg(escaped);
    }

    QString sql = QString("INSERT INTO %1 (%2) VALUES (%3);")
                      .arg(m_tableName)
                      .arg(columns.join(", "))
                      .arg(values.join(", "));
    auto callback = [this](bool success)
    {
        m_loading = false;
        if (success)
        {
            m_totalCount++;
        }
    };

    m_client->ExecuteOther(sql.toStdString(), callback);
    return true;
}

void RemoteTableModel::insertRowWithCallback(const QVariantMap &data, std::function<void(int)> callback)
{
    if (m_loading)
    {
        callback(-1); // 返回错误
        return;
    }
    m_loading = true;

    QStringList columns, values;
    for (auto it = data.begin(); it != data.end(); ++it)
    {
        columns << it.key();
        QString escaped;
        if (it.value().canConvert<QByteArray>())
        {
            escaped = QString::fromUtf8(it.value().toByteArray())
                          .replace("'", "''");
        }
        else
        {
            escaped = it.value().toString().replace("'", "''");
        }
        values << QString("'%1'").arg(escaped);
    }

    QString sql = QString("INSERT INTO %1 (%2) VALUES (%3) RETURNING id;")
                      .arg(m_tableName)
                      .arg(columns.join(", "))
                      .arg(values.join(", "));
    // 异步查询回调
    auto queryCallback = [this, callback](std::vector<Record> &records)
    {
        m_loading = false;
        if (!records.empty())
        {
            int newId = std::stoi(records[0]["data"]["id"]);
            m_totalCount++;
            callback(newId); // 返回新插入的 ID
        }
        else
        {
            callback(-1); // 插入失败
        }
    };
    m_client->ExecuteQuery(sql.toStdString(), queryCallback);
}

bool RemoteTableModel::updateRow(const QString &id, const QVariantMap &data)
{
    if (m_loading)
        return false;
    m_loading = true;

    // 构建 UPDATE 语句
    QStringList setClauses;
    for (auto it = data.begin(); it != data.end(); ++it)
    {
        QString escaped = it.value().toString().replace("'", "''");
        setClauses << QString("%1='%2'").arg(it.key()).arg(escaped);
    }

    QString sql = QString("UPDATE %1 SET %2 WHERE id='%3';")
                      .arg(m_tableName)
                      .arg(setClauses.join(", "))
                      .arg(id);

    auto callback = [this](bool success)
    {
        m_loading = false;
        if (success)
        {
            loadPage(m_currentPage); // 刷新当前页
            emit dataRefreshed();
        }
    };

    m_client->ExecuteOther(sql.toStdString(), callback);
    return true;
}

QString RemoteTableModel::getID(int row) const
{
    if (row < 0 || row >= m_records.size())
        return QString();
    const QVariantMap &record = m_records[row];
    QString id = record.value("id").toString();
    return id;
}

QVariantMap RemoteTableModel::getRowData(int row) const
{
    if (row >= 0 && row < m_records.size())
        return m_records[row];
    return QVariantMap();
}

void RemoteTableModel::loadPage(int page)
{
    if (m_loading)
        return;
    m_loading = true;
    beginResetModel();
    m_records.clear();

    m_client->ExecuteQuery(
        m_filter.toStdString(),
        [this](const std::vector<Record> &records)
        {
            QVector<QVariantMap> newData;
            for (const auto &record : records)
            {
                QVariantMap vm;
                auto dataMap = record.at("data");
                for (auto it = dataMap.begin(); it != dataMap.end(); ++it)
                {
                    const std::string &key = it->first;
                    const std::string &value = it->second;
                    vm[QString::fromStdString(key)] = QString::fromStdString(value);
                }
                newData.append(vm);
            }

            beginResetModel();   // 需要重新触发模型重置
            m_records = newData; // 直接赋值新数据
            endResetModel();     // 结束重置

            m_loading = false;
            emit loadFinished(newData); // 传递新数据到槽函数
        });
}
void RemoteTableModel::handleDataLoaded(const QVector<QVariantMap> &records)
{
    beginResetModel();

    m_records.clear();
    for (const auto &record : records)
    {
        QVariantMap normalizedRecord;

        // 数据标准化处理
        for (auto it = record.begin(); it != record.end(); ++it)
        {
            QString englishKey = it.key().toLower(); // 统一转小写
            if (englishKey == "total_count")
            {
                m_totalCount = it.value().toInt();
                continue;
            }
            if (COLUMN_MAPPING.contains(englishKey))
            {
                normalizedRecord[englishKey] = it.value();
            }
        }

        m_records.push_back(normalizedRecord);
    }

    endResetModel();

    emit dataRefreshed();
}
